<?php

namespace framework;

class Template
{
	//模板文件路径
	protected $tplPath;
	//缓存文件路径
	protected $tplCache;
	//缓存有效时间
	protected $validTime;
	//保存所有变量
	protected $vars = [];

	public function __construct(
									$tplPath='./view/',
									$tplCache='./caches/template/',
									$validTime=3600
								)
	{
		$this->tplPath = $this->checkDir($tplPath);
		$this->tplCache = $this->checkDir($tplCache);
		$this->validTime = $validTime;
	}

	public function assign($name,$value=null)
	{
		if (is_array($name)) {
			foreach ($name as $key => $value) {
				$this->vars[$key] = $value;
			}
		} else {
			$this->vars[$name] = $value;
		}
	}

	public function clearCache()
	{
		$this->clearDir($this->tplCache);
	}

	protected function clearDir($dir)
	{
		$dir = rtrim($dir,'/') . '/';
		$dp = opendir($dir);
		while ($file = readdir($dp)) {
			if ($file=='.' || $file=='..') {
				continue;
			}
			$fileName = $dir . $file;
			if (is_dir($fileName)) {
				$this->clearDir($fileName);
			} else {
				unlink($fileName);
			}
		}
		closedir($dp);
		rmdir($dir);
	}

	public function display($tplFile,$isExcute=true)
	{
		//0、拼接缓存文件路径名
		$cacheFile = $this->getCacheFile($tplFile);
		//1、拼接模板文件路径名
		$tplFile = $this->tplPath . $tplFile;
		//2、判断是否存在
		if (!file_exists($tplFile)) {
			exit($tplFile . '模板文件不存在');
		}
		//3、判断缓存文件是否存在
		if (!file_exists($cacheFile)
			||filemtime($cacheFile) < filemtime($tplFile)
			||filemtime($cacheFile) + $this->validTime < time()
			) {
			$this->checkDir(dirname($cacheFile));
			//编译模板文件
			$file = $this->compile($tplFile);
			//保存缓存文件
			file_put_contents($cacheFile, $file);
		} else {
			//更新包含文件
			$this->updateInclude($tplFile);
		}
		// echo $cacheFile;
		//4、是否执行该文件
		// if ($isExcute) {
		// 	//将分配的变量导入到当前符号表
		// 	extract($this->vars);
		// 	include $cacheFile;
		// }
		return $cacheFile;
	}

	protected function compile($tplFile)
	{
		//读取模板文件内容
		$file = file_get_contents($tplFile);
		//进行正则替换
		$keys = [
					'{$%%}'			=>	'<?=$\1;?>',
					'{if %%}'		=>	'<?php if (\1) { ?>',
					'{else}'		=>	'<?php } else { ?>',
					'{else if %%}'	=>	'<?php } else if (\1) { ?>',
					'{elseif %%}'	=>	'<?php } else if (\1) { ?>',
					'{/if}'			=>	'<?php } ?>',
					'{foreach %%}'	=>	'<?php foreach (\1): ?>',
					'{/foreach}'	=>	'<?php endforeach; ?>',
					'{section}'		=>	'<?php ',
					'{/section}'	=>	'?>',
					'{note}'		=>	'<?php /*',
					'{/note}'		=>	'*/?>',						
					'{include %%}'	=>	'这里都是骗人的东西',
					'{for %%}' 		=>  '<?php for (\1) :?>',
					'{/for}' 		=>  '<?php endfor;?>',
					'{while %%}' 	=>  '<?php while (\1) :?>',
					'{/while}' 		=>  '<?php endwhile;?>',
					'{continue}' 	=>  '<?php continue;?>',
					'{break}' 		=>  '<?php break;?>',
				];
		foreach ($keys as $key => $value) {
			//添加正则的转义
			$key = preg_quote($key,'#');
			//将其中的%%替换成(.+)
			$reg = '#' . str_replace('%%', '(.+)', $key) . '#U';
			if (strpos($reg, 'include')) {
				$file = preg_replace_callback($reg, [$this,'compileInclude'], $file);
			} else {
				$file = preg_replace($reg, $value, $file);
			}
		}
		//返回替换后的内容
		return $file;
	}

	protected function compileInclude($matches)
	{
		//去掉文件包含两边的引号
		$fileName = trim($matches[1],'\'"');
		$this->display($fileName,false);
		$cacheFile = $this->getCacheFile($fileName);
		return "<?php include '$cacheFile'; ?>";
	}

	protected function updateInclude($file)
	{
		//读取模板文件内容
		$content = file_get_contents($file);
		//找到包含的模板文件，然会后进行编译
		if (preg_match_all('/\{include (.+)\}/U', $content, $matches)) {
			foreach ($matches[1] as $value) {
				$tplFile = trim($value,'\'"');
				$this->display($tplFile,false);
			}
		}
	}

	protected function checkDir($dir)
	{
		$dir = rtrim($dir,'/') . '/'; 
		if (!is_dir($dir)) {
			mkdir($dir,0777,true);
		}
		if (!is_readable($dir) || !is_writable($dir)) {
			chmod($dir, 0777);
		}
		return $dir;
	}

	protected function getCacheFile($file)
	{
		return $this->tplCache . str_replace('.','_',$file) . '.php';
	}
}